package cn.wen.bases.framework.spring;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * Title：Spring 工具类
 * <p>
 * Description：提供Spring上下文。
 * <p>
 * Copyright：Copyright (c) 2010-2012
 * 
 * @author <a href="mailto:ct_wen@qq.com">ctwen</a>, 温承瑭
 * @version Revision：1.0 Date：2010/11/20 Description：初完成。
 *          <p>
 *          Revision：1.1 Date：2011/3/23 Description：基本功能不变，内部结构整体优化；成员变量ac被volatile修饰，使用了较弱的安全同步机制。
 */
public final class UtilsOfSpring implements ApplicationContextAware {
    
    /**
     * @see #getWebApplicationContext()
     */
    public static Object getBean(String name) {
	return getWebApplicationContext().getBean(name);
    }
    
    /**
     * @see #getWebApplicationContext()
     */
    public static <T> T getBean(String name, Class<T> clz) {
	return getWebApplicationContext().getBean(name, clz);
    }

    /**
     * @see #getWebApplicationContext()
     */
    public static <T> T getBean(Class<T> clz) {
	return getWebApplicationContext().getBean(clz);
    }

    /**
     * 获取WebApplicationContext，注：依赖Web容器。
     * 
     * @return WebApplicationContext instance
     * @throws IllegalStateException if not running in a WebApplicationContext
     */
    public static WebApplicationContext getWebApplicationContext() throws IllegalStateException {
	return getWebApplicationContext(getServletContext());
    }

    /**
     * 获取WebApplicationContext，注：依赖Web容器。
     * 
     * @see #getWebApplicationContext()
     * @return WebApplicationContext instance
     * @throws IllegalStateException if not running in a WebApplicationContext
     */
    public static WebApplicationContext getWebApplicationContext(ServletContext sc) throws IllegalStateException {
	// 从Servlet容器中得到Spring上下文
	//WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
	return WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
    }

    /**
     * 获取当前HttpServletRequest实例，注：依赖Web容器。
     * 
     * @return HttpServletRequest instance
     */
    public static final HttpServletRequest getHttpServletRequest() {
	return currentRequestAttributes().getRequest();
    }

    /**
     * Return the current RequestAttributes instance as ServletRequestAttributes.
     * 
     * @see org.springframework.web.context.request.RequestContextHolder#currentRequestAttributes()
     */
    private static ServletRequestAttributes currentRequestAttributes() {
	RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();

	if (!(requestAttr instanceof ServletRequestAttributes)) {
	    throw new IllegalStateException("Current request is not a servlet request");
	}

	return (ServletRequestAttributes) requestAttr;
    }
    
    public static final ServletContext getServletContext() {
	return ContextLoader.getCurrentWebApplicationContext().getServletContext();
    }
    

    private static volatile ApplicationContext ac;

    /**
     * 获取ApplicationContext，注：不依赖Web容器。
     * 
     * @deprecated
     * @see #getWebApplicationContext()
     * @return ApplicationContext instance
     */
    public static ApplicationContext getApplicationContext() {
	return ac;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
     */
    @Override
    public void setApplicationContext(ApplicationContext ac) throws BeansException {
	UtilsOfSpring.ac = ac;
    }

}
